#include <TcpConnection.h>

int processRead(void* arg) {
    struct TcpConnection* conn = (struct TcpConnection*) arg;
    int count = bufferSocketRead(conn->readBuf, conn->channel->fd);

    if(count > 0) {
        int socket = conn->channel->fd;

        bool flag = parseHttpRequest(conn->request, conn->readBuf, conn->response, conn->writeBuf, socket);
        if(!flag) {
            char * errMsg = "Http/1.1 400 Bad Request\r\n\r\n";
            bufferAppendString(conn->writeBuf, errMsg);
        }
    } else {
        eventLoopAddTask(conn->evLoop, conn->channel, DELETE);
    }
    return 0;
}

int processWrite(void* arg) {
    struct TcpConnection* conn = (struct TcpConnection*)arg;

    int count = bufferSendData(conn->writeBuf, conn->channel->fd);
    if(count > 0) {
        if(bufferReadableSize(conn->writeBuf) == 0) {
            writeEventEnable(conn->channel, false);

            eventLoopAddTask(conn->evLoop, conn->channel, MODIFY);

            eventLoopAddTask(conn->evLoop, conn->channel, DELETE);
        }
    }
    return 0;
}

struct TcpConnection* tcpConnectionInit(int fd, struct EventLoop* evLoop) {
    struct TcpConnection* conn = (struct TcpConnection*)malloc(sizeof (struct TcpConnection));
    conn->evLoop = evLoop;
    conn->readBuf = bufferInit(10240);
    conn->writeBuf = bufferInit(10240);


    conn->request = httpRequestInit();
    conn->response = httpResponseInit();

    sprintf(conn->name, "Connection-%d", fd);
    conn->channel = channelInit(fd, ReadEvent, processRead,processWrite,
                                tcpConnectionDestroy, conn);
    eventLoopAddTask(evLoop, conn->channel, ADD);
    return conn;
}

int tcpConnectionDestroy(void* arg) {
    struct TcpConnection* conn = (struct TcpConnection*)arg;
    if(conn != NULL) {
        if(conn->readBuf && bufferReadableSize(conn->readBuf) == 0 &&
           conn->writeBuf && bufferReadableSize(conn->writeBuf) == 0) {
            destroyChannel(conn->evLoop, conn->channel);
            bufferDestory(conn->readBuf);
            bufferDestory(conn->writeBuf);
            free(conn);
        }
    }
    return 0;
}
